package com.basker.pisces.concurrent.lock;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public abstract class AbstractLockManager implements ILockManager {
    private String name;
    private final ConcurrentMap<String, ILock> lockMap = new ConcurrentHashMap<>(16);
    private Set<String> lockKeys = Collections.emptySet();

    public AbstractLockManager(String name) {
        this.name = name;
    }

    @Override
    public ILock getLock(String key) {
        ILock lock = this.lockMap.get(key);
        if (lock != null) {
            return lock;
        } else {
            synchronized (this.lockMap) {
                lock = this.lockMap.get(key);

                if (lock == null) {
                    lock = createLock(key);
                    if (lock != null) {
                        this.lockMap.put(key, lock);
                        updateLockKeys(key);
                    }
                }
                return lock;
            }
        }
    }

    @Override
    public Collection<String> getLockKeys() {
        return this.lockKeys;
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected abstract ILock createLock(String key);

    protected ConcurrentMap<String, ILock> getLockMap() {
        return lockMap;
    }

    private void updateLockKeys(String key) {
        Set<String> lockKeys = new LinkedHashSet<>(this.lockKeys.size() + 1);
        lockKeys.addAll(this.lockKeys);
        lockKeys.add(key);
        this.lockKeys = Collections.unmodifiableSet(lockKeys);
    }
}
